/*     */ package com.zimbra.cs.gal;
/*     */ 
/*     */ import com.zimbra.common.mailbox.ContactConstants;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.DateUtil;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.DataSource;
/*     */ import com.zimbra.cs.account.GalContact;
/*     */ import com.zimbra.cs.account.GalContact.Visitor;
/*     */ import com.zimbra.cs.account.Provisioning;
/*     */ import com.zimbra.cs.account.Provisioning.SearchGalResult;
/*     */ import com.zimbra.cs.account.ldap.LdapGalMapRules;
/*     */ import com.zimbra.cs.datasource.MailItemImport;
/*     */ import com.zimbra.cs.db.DbDataSource;
/*     */ import com.zimbra.cs.db.DbDataSource.DataSourceItem;
/*     */ import com.zimbra.cs.mailbox.Contact;
/*     */ import com.zimbra.cs.mailbox.MailItem.Type;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.mailbox.MailboxIndex;
/*     */ import com.zimbra.cs.mailbox.Metadata;
/*     */ import com.zimbra.cs.mailbox.OperationContext;
/*     */ import com.zimbra.cs.mime.ParsedContact;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Collections;
/*     */ import java.util.Date;
/*     */ import java.util.HashMap;
/*     */ import java.util.HashSet;
/*     */ import java.util.Iterator;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import java.util.Map.Entry;
/*     */ import org.json.JSONException;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class GalImport
/*     */   extends MailItemImport
/*     */ {
/*     */   private static final String TYPE = "t";
/*     */   private static final String FOLDER = "f";
/*     */   public static final String SYNCTOKEN = "st";
/*     */   
/*     */   public GalImport(DataSource ds)
/*     */     throws ServiceException
/*     */   {
/*  50 */     super(ds);
/*     */   }
/*     */   
/*     */   public void importData(List<Integer> folderIds, boolean fullSync) throws ServiceException
/*     */   {
/*     */     Iterator i$;
/*  56 */     if (folderIds == null) {
/*  57 */       importGal(this.dataSource.getFolderId(), fullSync, false);
/*     */     } else
/*  59 */       for (i$ = folderIds.iterator(); i$.hasNext();) { int fid = ((Integer)i$.next()).intValue();
/*  60 */         importGal(fid, fullSync, false);
/*     */       }
/*     */   }
/*     */   
/*     */   public void test() throws ServiceException {
/*  65 */     searchGal(null, Provisioning.SearchGalResult.newSearchGalResult(null), false);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   private void setStatus(boolean success)
/*     */     throws ServiceException
/*     */   {
/*  73 */     Date now = new Date();
/*  74 */     DataSource ds = getDataSource();
/*  75 */     Map<String, Object> attrs = new HashMap();
/*  76 */     String attr = success ? "zimbraGalLastSuccessfulSyncTimestamp" : "zimbraGalLastFailedSyncTimestamp";
/*     */     
/*     */ 
/*  79 */     attrs.put(attr, DateUtil.toGeneralizedTime(now));
/*  80 */     Provisioning.getInstance().modifyDataSource(ds.getAccount(), ds.getId(), attrs);
/*     */   }
/*     */   
/*     */   public void importGal(int fid, boolean fullSync, boolean force) throws ServiceException {
/*  84 */     this.mbox.beginTrackingSync();
/*  85 */     DataSource ds = getDataSource();
/*  86 */     DbDataSource.DataSourceItem folderMapping = DbDataSource.getMapping(ds, fid);
/*  87 */     if (folderMapping.md == null) {
/*  88 */       folderMapping.itemId = fid;
/*  89 */       folderMapping.md = new Metadata();
/*  90 */       folderMapping.md.put("t", "f");
/*  91 */       DbDataSource.addMapping(ds, folderMapping);
/*     */     }
/*  93 */     String syncToken = fullSync ? "" : folderMapping.md.get("st", "");
/*  94 */     HashMap<String, DbDataSource.DataSourceItem> allMappings = new HashMap();
/*  95 */     if ((fullSync) || (force))
/*  96 */       for (DbDataSource.DataSourceItem dsItem : DbDataSource.getAllMappings(ds))
/*  97 */         if ((dsItem.md == null) || (dsItem.md.get("t", null) == null))
/*  98 */           allMappings.put(dsItem.remoteId, dsItem);
/*  99 */     OperationContext octxt = new OperationContext(this.mbox);
/* 100 */     Provisioning.SearchGalResult result = Provisioning.SearchGalResult.newSearchGalResult(new GalSearchVisitor(this.mbox, allMappings, fid, force, null));
/*     */     try {
/* 102 */       searchGal(syncToken, result, true);
/*     */     } catch (Exception e) {
/* 104 */       setStatus(false);
/* 105 */       ZimbraLog.gal.error("Error executing gal search", e);
/* 106 */       return;
/*     */     }
/*     */     
/* 109 */     folderMapping.md.put("st", result.getToken());
/* 110 */     DbDataSource.updateMapping(ds, folderMapping);
/* 111 */     if ((allMappings.size() == 0) || (!fullSync)) {
/* 112 */       setStatus(true);
/* 113 */       return;
/*     */     }
/*     */     
/* 116 */     ArrayList<Integer> deleted = new ArrayList();
/* 117 */     int[] deletedIds = new int[allMappings.size()];
/* 118 */     int i = 0;
/* 119 */     for (DbDataSource.DataSourceItem dsItem : allMappings.values()) {
/* 120 */       deleted.add(Integer.valueOf(dsItem.itemId));
/* 121 */       deletedIds[(i++)] = dsItem.itemId;
/*     */     }
/*     */     try {
/* 124 */       this.mbox.delete(octxt, deletedIds, MailItem.Type.CONTACT, null);
/*     */     } catch (ServiceException e) {
/* 126 */       ZimbraLog.gal.warn("Ignoring error deleting gal contacts", e);
/*     */     }
/* 128 */     DbDataSource.deleteMappings(getDataSource(), deleted);
/* 129 */     this.mbox.index.optimize();
/* 130 */     setStatus(true);
/*     */   }
/*     */   
/*     */   private void searchGal(String syncToken, Provisioning.SearchGalResult result, boolean fetchGroupMembers) throws ServiceException {
/* 134 */     ZimbraLog.gal.debug("searchGal: " + syncToken);
/* 135 */     DataSource ds = getDataSource();
/* 136 */     GalSearchParams params = new GalSearchParams(ds);
/* 137 */     params.setGalResult(result);
/* 138 */     params.setToken(syncToken);
/* 139 */     params.setQuery("*");
/* 140 */     for (String attr : ZIMBRA_ATTRS)
/* 141 */       params.getConfig().getRules().add(attr + "=" + attr);
/* 142 */     params.getConfig().getRules().setFetchGroupMembers(fetchGroupMembers);
/* 143 */     params.getConfig().getRules().setNeedSMIMECerts(true);
/* 144 */     Provisioning.getInstance().searchGal(params); }
/*     */   
/* 146 */   private static String[] ZIMBRA_ATTRS = { "zimbraNotes", "zimbraAccountCalendarUserType", "zimbraCalResType", "zimbraCalResLocationDisplayName", "zimbraCalResCapacity", "zimbraCalResContactEmail" };
/*     */   
/*     */ 
/*     */   private class GalSearchVisitor
/*     */     implements GalContact.Visitor
/*     */   {
/*     */     Mailbox mbox;
/*     */     
/*     */     OperationContext octxt;
/*     */     
/*     */     Map<String, DbDataSource.DataSourceItem> mappings;
/*     */     int fid;
/*     */     boolean force;
/*     */     
/*     */     private GalSearchVisitor(Map<String, DbDataSource.DataSourceItem> mbox, int mappings, boolean fid)
/*     */       throws ServiceException
/*     */     {
/* 163 */       this.mbox = mbox;
/* 164 */       this.octxt = new OperationContext(mbox);
/* 165 */       this.mappings = mappings;
/* 166 */       this.fid = fid;
/* 167 */       this.force = force;
/*     */     }
/*     */     
/* 170 */     private final String[] FILE_AS_STR_KEYS = { ContactConstants.A_fullName, ContactConstants.A_email, ContactConstants.A_email2, ContactConstants.A_email3 };
/*     */     
/*     */ 
/*     */     private static final String MODIFY_TIMESTAMP = "modifyTimeStamp";
/*     */     
/*     */ 
/*     */     private void addFileAsStr(Map<String, Object> attrs)
/*     */     {
/* 178 */       for (String key : this.FILE_AS_STR_KEYS) {
/* 179 */         Object fileAsStr = attrs.get(key);
/* 180 */         if ((fileAsStr != null) && ((fileAsStr instanceof String))) {
/* 181 */           attrs.put(ContactConstants.A_fileAs, "8:" + (String)fileAsStr);
/* 182 */           return;
/*     */         }
/*     */       }
/*     */     }
/*     */     
/*     */     public void visit(GalContact contact) throws ServiceException
/*     */     {
/* 189 */       Map<String, Object> attrs = contact.getAttrs();
/* 190 */       String id = contact.getId();
/* 191 */       this.mappings.remove(id);
/* 192 */       attrs.put(ContactConstants.A_dn, id);
/* 193 */       ZimbraLog.gal.debug("processing gal contact " + id);
/* 194 */       DbDataSource.DataSourceItem dsItem = DbDataSource.getReverseMapping(GalImport.this.getDataSource(), id);
/* 195 */       addFileAsStr(attrs);
/* 196 */       if (dsItem.itemId == 0) {
/* 197 */         ZimbraLog.gal.debug("creating new contact " + id);
/* 198 */         dsItem.remoteId = id;
/* 199 */         ParsedContact pc = new ParsedContact(attrs);
/* 200 */         dsItem.itemId = this.mbox.createContact(this.octxt, pc, this.fid, null).getId();
/* 201 */         DbDataSource.addMapping(GalImport.this.getDataSource(), dsItem);
/*     */       } else {
/* 203 */         Contact mboxContact = this.mbox.getContactById(this.octxt, dsItem.itemId);
/*     */         
/*     */ 
/* 206 */         String syncDate = mboxContact.get("modifyTimeStamp");
/* 207 */         String modifiedDate = (String)contact.getAttrs().get("modifyTimeStamp");
/* 208 */         if ((!this.force) && (syncDate != null) && (syncDate.equals(modifiedDate))) {
/* 209 */           ZimbraLog.gal.debug("gal contact %s has not been modified", new Object[] { id });
/* 210 */           return;
/*     */         }
/* 212 */         if ((!this.force) && (allFieldsMatch(attrs, mboxContact.getAllFields()))) {
/* 213 */           ZimbraLog.gal.debug("no field has changed in gal contact %s", new Object[] { id });
/* 214 */           return;
/*     */         }
/*     */         
/* 217 */         ZimbraLog.gal.debug("modifying contact " + id);
/* 218 */         ParsedContact pc = new ParsedContact(attrs);
/* 219 */         this.mbox.modifyContact(this.octxt, dsItem.itemId, pc);
/*     */       }
/*     */     }
/*     */     
/*     */ 
/*     */     private boolean allFieldsMatch(Map<String, Object> ldapContact, Map<String, String> contact)
/*     */     {
/* 226 */       if (ldapContact.size() != contact.size())
/* 227 */         return false;
/* 228 */       HashSet<String> ignoredKeys = new HashSet();
/*     */       
/* 230 */       ignoredKeys.add("modifyTimeStamp");
/* 231 */       Collections.addAll(ignoredKeys, GalImport.this.dataSource.getMultiAttr("zimbraGalSyncIgnoredAttributes"));
/* 232 */       for (Map.Entry<String, Object> entry : ldapContact.entrySet()) {
/* 233 */         String key = (String)entry.getKey();
/* 234 */         if (!ignoredKeys.contains(key))
/*     */         {
/* 236 */           Object ldapValue = entry.getValue();
/* 237 */           if ((ldapValue instanceof String)) {
/* 238 */             String contactValue = (String)contact.get(key);
/* 239 */             if (!((String)ldapValue).equals(contactValue))
/* 240 */               return false;
/* 241 */           } else if ((ldapValue instanceof String[])) {
/*     */             try {
/* 243 */               String encodedValue = Contact.encodeMultiValueAttr((String[])ldapValue);
/* 244 */               if (!encodedValue.equals(contact.get(key)))
/* 245 */                 return false;
/*     */             } catch (JSONException e) {
/* 247 */               return false;
/*     */             }
/*     */           }
/*     */         } }
/* 251 */       return true;
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/gal/GalImport.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */